# coding utf8
import random
from random import randrange
import time
import os

from docx import Document
from docx.shared import Pt
from docx.oxml.ns import qn
from docx.shared import Inches
from docx.shared import Length
from docx.shared import Mm
# 会有红色下划线报异常，不过可以正常使用
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_TAB_ALIGNMENT, WD_TAB_LEADER

explist = []


# 100内的加法
def addexps(va=0):
    a = 0
    b = 0
    s = 0
    again = 1

    while again:
        a = random.randint(1, 100)
        b = random.randint(1, 100)
        s = a + b
        if s <= 100:
            again = 0

    return {'c': '＋', 'a': a, 'b': b, 's': s, 'y': 0}

# 100内的减法


def subexps(va=0):
    a = 0
    b = 0
    s = 0
    again = 1

    while again:
        a = random.randint(1, 100)
        b = random.randint(1, 100)
        s = a - b
        if s >= 0:
            again = 0

    return {'c': '—', 'a': a, 'b': b, 's': s, 'y': 0}


# 表内乘法
def mulexps(va=0):
    a = 0
    b = 0
    s = 0
    again = 1

    while again:
        a = random.randint(1, 100)
        b = random.randint(1, 100)
        s = a * b
        if s <= 100:
            again = 0

    return {'c': '×', 'a': a, 'b': b, 's': s, 'y': 0}


# 表内除法
def divexps(ys=0):
    a = 0
    b = 0
    s = 0
    y = 0
    again = 1

    while again:
        a = random.randint(0, 89)
        b = random.randint(1, 9)

        # 判断被除数小于除数，跳过
        if a < b:
            continue
        elif a // b > 9:
            continue

        s = 0
        y = 0

        s = a // b
        y = a - b * s

        if y > 0 and ys == 0:
            continue

        again = 0
    exp = {'c': '÷', 'a': a, 'b': b, 's': s, 'y': y}
    return exp


# 表内除法全集
def div_ys_expfull():
    pa = []
    pb = []

    while len(pa) < 90:
        a = random.randint(0, 89)
        if a in pa:
            continue
        pa.append(a)

        pb = []
        while len(pb) < 9:
            if a == 0:
                break

            b = random.randint(1, 9)
            if b in pb:
                continue
            pb.append(b)

            s = a // b
            y = a - b * s

            # 商大于等于10的先不加入
            if s >= 10:
                continue

            # 被除数大于除数的晢时不加入
            if a >= b:
                exp = {'c': '÷', 'a': a, 'b': b, 's': s, 'y': y}
                explist.append(exp)

# 千以内加减法


def thr_sum_sub():
    s = 0
    a = 0
    b = 0
    ysf = 0
    again = 1

    ysflist = {0: lambda x, y: x+y, 1: lambda x, y: x-y}

    while again:
        a = random.randint(1, 1000)
        b = random.randint(1, 1000)
        ysf = random.randint(0, 1)
        s = ysflist[ysf](a, b)

        if (s < 0) or (s > 1000):
            continue
        else:
            break

    ysf = '＋' if ysf == 0 else '—'

    exp = {'c': ysf, 'a': a, 'b': b, 's': s, 'y': 0}
    return exp


# 万以内加减法
def muil_sum_sub():
    s = 0
    a = 0
    b = 0
    ysf = 0
    again = 1

    ysflist = {0: lambda x, y: x+y, 1: lambda x, y: x-y}

    while again:
        a = random.randint(1000, 10000)
        b = random.randint(1000, 10000)
        ysf = random.randint(0, 1)
        s = ysflist[ysf](a, b)

        if (s < 0) or (s > 10000):
            continue
        else:
            break

    ysf = '＋' if ysf == 0 else '—'

    exp = {'c': ysf, 'a': a, 'b': b, 's': s, 'y': 0}
    return exp


# 两位数相加，过百
def add_over_thund():
    s = 0
    a = 0
    b = 0

    again = True
    while again:
        a = random.randint(0, 100)
        b = random.randint(0, 100)
        s = a + b
        if s < 100:
            continue
        else:
            break

    exp = {'c': '＋', 'a': a, 'b': b, 's': s, 'y': 0}
    return exp

# 百位数减十位数


def sub_100():
    s = 0
    a = 100
    b = random.randint(0, 100)
    s = a - b

    exp = {'c': '—', 'a': a, 'b': b, 's': s, 'y': 0}

    return exp


def mul_2to1():
    s = 0
    a = 0
    b = 0

    a = random.randint(10, 100)
    b = random.randint(1, 10)
    s = a * b

    exp = {'c': '×', 'a': a, 'b': b, 's': s, 'y': 0}
    return exp


def mul_2to2():
    s = 0
    a = 0
    b = 0

    a = random.randint(10, 100)
    b = random.randint(10, 100)
    s = a * b

    exp = {'c': '×', 'a': a, 'b': b, 's': s, 'y': 0}
    return exp

# 检查表达式的重复


def checkrange(exp):
    if exp in explist:
        return False
    else:
        explist.append(exp)


expname = {
    1: {1: "[1]: 百以内加法", 'fun': addexps}, 
    2: {1: "[2]: 百以内减法", 'fun': subexps}, 
    3: {1: "[3]: 表内乘法", 'fun': mulexps}, 
    4: {1: "[4]: 表内除法", 'fun': divexps}, 
    5: {1: "[5]: 表内除法有余数", 'fun': divexps}, 
    6: {1: "[6]: 表内除法全集", 'fun': div_ys_expfull}, 
    7: {1: "[7]: 随机生成算式", 'fun': ''}, 
    8: {1: "[8]: 千以内加减法", 'fun': thr_sum_sub}, 
    9: {1: "[9]: 万以内加减法", 'fun': muil_sum_sub}, 
    10: {1: "[10]:两位数相加，过百", 'fun': add_over_thund}, 
    11: {1: "[11]:百位数减两位数", 'fun': sub_100}, 
    12: {1: "[12]:二位数乘一位数", 'fun': mul_2to1}, 
    13: {1: "[13]:二位数乘二位数", 'fun': mul_2to2}, 
    0: {1: "[0]: 退出", 'fun': exit}
}


actname = (
    "[1]: 填写运算符左边的数", "[2]: 填写运算符右边的数", "[3]: 填写运算结果", "[4]: 随机生成版式")


def main():
    global explist

    errorcode = 0
    cnt = 0
    slt1 = 0  # 选择运算方式，1=加，2=减， 3=乘， 4=除
    slt2 = 0  # 选择生成的运算式类型，0=计算结果，1=计算运算符左边的数值，2= 计算运算符右边的数值
    exp = []
    hpy = 0
    title = ''

    while errorcode == 0:
        for itc in expname:
            print(expname[itc][1])

        slt1 = input("请选择计算类型：")
        slt1 = int(slt1)
        if slt1 >= len(expname):
            errorcode = 1
            print("程序结束,谢谢使用。")
            exit(0)

        if slt1 == 0:
            exit()

        cnt = input("请输入计算式的数量：")
        cnt = int(cnt)
        if cnt <= 0:
            continue

        for itc in actname:
            print(itc)

        slt2 = input("请选择填写方式：")
        slt2 = int(slt2)
        if slt2 <= 0 or slt2 > len(actname):
            continue

        if slt1 == 7:  # 随机生成
            hpy = 1

        title = expname[slt1][1]

        i = 0

        while i < cnt:
            if hpy == 1:  # 随机生成
                slt1 = random.randint(1, len(expname)-2)
                if slt1 == 6:
                    continue

            if slt1 == 5:
                exp = divexps(ys=1)
            elif slt1 == 6:
                expname[slt1]['fun']()
                break
            else:
                exp = expname[slt1]['fun']()

            exp['i'] = i % 50

            if checkrange(exp) == False:
                continue
            i += 1

        outexplist(slt2, title)
        explist = []
        hpy = 0


def outexplist(hpy, title=''):
    global explist
    cnt = 0
    c = 0
    tmpstr = ''

    time_stamp = time.time()
    time_stamp = int(round(time_stamp * 10))

    basename = f'{os.getcwd()}//{time_stamp}'
    filename = f'{basename}.txt'
    docxname = f'{basename}.docx'


    fp = open(filename, 'w+')

    for exp in explist:
        if cnt % 50 == 0:
            c += 1
            print(f"\n\n{title}口算卡（{c}）", file=fp)

        if hpy == 4:
            typd = random.randint(1, len(actname)-1)
        else:
            typd = hpy

        if exp['y'] == 0:
            exp['y'] = ' '
            tmpstr = f"{exp['y']:2}   "
        else:
            tmpstr = f"…{exp['y']: 2}  "

        if typd == 1:
            print(
                f"{'__':2}{exp['c']}{exp['b']:2}={exp['s']:^3}"+tmpstr, end='', file=fp)
        elif typd == 2:
            print(f"{exp['a']:2}{exp['c']}{'__':2}={exp['s']:^3}" + tmpstr, end='', file=fp)
        elif typd == 3:
            print(f"{exp['a']:4}{exp['c']}{exp['b']:4}={' ':^6}", end='', file=fp)

        cnt += 1
        if cnt % 5 == 0:
            print('', file=fp)

    fp.close()

    # 生成word文档
    document = Document()
    fp = open(filename, 'r')
    lines = fp.readlines()
    paragraph = document.add_paragraph()
    # paragraph.line_spacing_rule = WD_LINE_SPACING.MULTIPLE #多倍行距
    paragraph.paragraph_format.line_spacing = 1.75  # 1.75倍行间距
    paragraph.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.LEFT
    document.sections[0].page_height = Mm(297)
    document.sections[0].page_width = Mm(210)
    document.sections[0].left_margin = Mm(12.4)
    document.sections[0].right_margin = Mm(20.4)
    document.sections[0].top_margin = Mm(25.4)
    document.sections[0].bottom_margin = Mm(25.4)
    document.sections[0].header_distance = Mm(12.7)
    document.sections[0].footer_distance = Mm(12.7)

    for line in lines:
        # 添加文本#设置字号字体
        run = paragraph.add_run(format('%s' % line))
        run.font.size = Pt(12)
        run.font.name = u'宋体'

    fp.close()
    os.remove(filename)
    document.save(docxname)

    os.startfile(docxname)  # 调用系统程序，打开文件


if __name__ == "__main__":
    main()
